﻿using System;
using System.IO;
using System.Linq;
using System.Text;
using FFmpegVideoClip.Configuration;
using FFmpegVideoClip.Lib;
using FFmpegVideoClip.Lib.Processing;
using UtilityToolsCollect.ObjectsLibrary.ProcessManage;
using UtilityToolsCollect.ObjectsLibrary.TaskFlowProcessor;

namespace FFmpegVideoClip.Processing
{
    public class LosslessMergeTask : TaskProcessor, ITaskInfo
    {
        public TimeSpan ProcessorTime { get; set; }
        public bool IsError { get; set; } = true;

        private string m_Arguments;

        private bool IsAllow = true;

        private bool IsMergeMode = false;

        private string? ProcessorName;
        public int ProcessorCount;
        private bool IsRm = false;
        StringBuilder Info = new();
        public LosslessMergeTask(Clip clip, bool OriginalInputMode = false)
        {
            if (clip == null)
            {
                //throw new NullReferenceException($"[{typeof(Clip)}]类型参数[{nameof(clip)}] 是一个空实例");
                IsAllow = false;
                m_Arguments = string.Empty;
                return;
            }
            SourceData = clip;
            if (clip.Count < 2)
            {
                m_Arguments = string.Empty;
                return;
            }
            ProcessorName = Path.GetExtension(clip.FileWritePath).StartsWith(".rm", StringComparison.OrdinalIgnoreCase) ? LosslessSplitTask.RMProcessor : LosslessSplitTask.FFProcessor;
            ProcessorCount = clip.Count;
            StringBuilder sb = new StringBuilder();
            try
            {
                if (ProcessorName == LosslessSplitTask.RMProcessor)
                {
                    IsRm = true;
                    foreach (Fragment item in clip.Fragments)
                        sb.Append($"-i \"{(OriginalInputMode ? item.InputPath : item.GetFileWritePath())}\" ");
                }
                else
                {
                    foreach (Fragment item in clip.Fragments)
                        sb.AppendLine($"file '{(OriginalInputMode ? item.InputPath : item.GetFileWritePath())}'");
                }
                    
            }
            catch (Exception)
            {
                IsAllow = false;
            }
            string OutFileName = clip.FileWritePath;
            Tools.CheckDirectoryPath(Path.GetDirectoryName(OutFileName)!, out _, true);
            Tools.CheckDuplicateNameAndLegal(ref OutFileName);
            clip.FileWritePath = OutFileName;
            if (IsRm)
                m_Arguments = $"{sb.ToString()}-o \"{clip.FileWritePath}\"" ;
            else
            {
                string infoFilePath = Path.Combine(Path.GetDirectoryName(clip.Fragments.First().TempWritePath)!, $"MergeInformation_[{clip.Name}].txt");
                File.WriteAllText(infoFilePath, sb.ToString());
                m_Arguments = Tools.FFmpegMergeArguments(infoFilePath, clip.FileWritePath);
            }

            IsMergeMode = true;
        }
        public override void Execute()
        {
            if (!IsAllow)
                return;
            try
            {
                if (IsMergeMode)
                {
                    Info.AppendLine($"[合并]:{ProcessorName} {m_Arguments}");
                    ProcessShell.ProcessExecuteWaitForExit(ProcessorName!, m_Arguments, SetTaskInfo, SetTaskInfo);
                }
                else
                {
                    Clip clip = (Clip)SourceData!;
                    Fragment fragment = clip.Fragments.First();
                    Info.AppendLine($"移动: [{fragment.TempWritePath}] ==> [{clip.FileWritePath}]");
                    File.Move(fragment.TempWritePath, clip.FileWritePath, true);
                }
            } catch (Exception exc) 
            {
               throw new LosslessMergeTaskRunException($"执行错误:信息:[{Info.ToString()}]", exc);
            }
            LogManage.WriteLineNewInfo(Info.ToString());
            Info.Clear();
            Info = null!;
            ProcessorTime = new TimeSpan(0,0,1);
        }

        public void SetTaskInfo(string? value)
        {
            if (string.IsNullOrWhiteSpace(value))
                return;
            Info.AppendLine(value);
            if(IsRm)
            {
                if (value.Contains("Processing complete!"))
                    IsError = false;
            }
            else if (Config.FFmpegSuccessValidated.IsMatch(value))
            {
                IsError = false;
            }
        }


        [Serializable]
        public class LosslessMergeTaskRunException : Exception
        {
            public LosslessMergeTaskRunException() { }
            public LosslessMergeTaskRunException(string message) : base(message) { }
            public LosslessMergeTaskRunException(string message, Exception inner) : base(message, inner) { }
            [Obsolete] protected LosslessMergeTaskRunException(
              System.Runtime.Serialization.SerializationInfo info,
              System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
        }
    }
}
